﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml.Schema;

namespace XmlConverter {
	public partial class MainForm : Form {
		public MainForm() {
			InitializeComponent();
		}

		private void MainFormLoad(object sender, EventArgs e) {

		}

		private void BrouseSourceButtonClick(object sender, EventArgs e) {
			var result = _open_dialog.ShowDialog();
			if (result == DialogResult.OK) {
				_source_file.Text = _open_dialog.FileName;
			}

		}

		private void BrowseDestButtonClick(object sender, EventArgs e) {
			if (!string.IsNullOrWhiteSpace(_dest_path.Text)) {
				_save_dialog.SelectedPath = _dest_path.Text;
			}

			var result = _save_dialog.ShowDialog();
			if (result == DialogResult.OK) {
				_dest_path.Text = _save_dialog.SelectedPath;
			}
		}

		class InputValidationException : Exception {
			public InputValidationException(string message) : base(message) {}
		}

		static void FailValidation(string message) {
			throw new InputValidationException(message);
		}

		static void CheckInputPath(string path) {
			if (string.IsNullOrEmpty(path)) {
				FailValidation("You must specify source path");
			}

			else if (!File.Exists(path)) {
				FailValidation(string.Format("File {0} doesn't exist", path));
			}
		}

		static string ToString(ICollection<char> chars) {
			var string_builder = new StringBuilder(chars.Count);
			foreach (var c in chars) {
				string_builder.Append(c);
			}

			return string_builder.ToString();
		}

		static void CheckOutputPath(string path) {
			if (string.IsNullOrEmpty(path)) {
				FailValidation("You must specify output path");
			}

			var folder = Path.GetDirectoryName(path);
			if (string.IsNullOrWhiteSpace(folder) || !Directory.Exists(folder)) {
				FailValidation(string.Format("Directory {0} does not exist", folder));
			}

			var file = Path.GetFileName(path);
			if (string.IsNullOrWhiteSpace(file) || file.Contains(ToString(Path.GetInvalidFileNameChars()))) {
				FailValidation(string.Format("Invalid file name: {0}", file));
			}
		}

		static void ValidateInput(string input_path, string output_path) {
			CheckInputPath(input_path);
			CheckOutputPath(output_path);
		}

		static void ValidationHandler(object sender, ValidationEventArgs e) {
			if (e.Severity == XmlSeverityType.Error) {
				throw new InvalidOperationException(e.Message);
			}
		}

		static XmlSchema ReadSchema(string path) {
			using (var stream = File.OpenRead(path)) {
				return XmlSchema.Read(stream, ValidationHandler);
			}
		}

		static XmlSchemaSet GetSchemas() {
			
			var directory = AppDomain.CurrentDomain.BaseDirectory;

			var path = Path.Combine(directory, "data.xsd");

			var schema = ReadSchema(path);

			var result = new XmlSchemaSet();
			result.Add(schema);

			return result;
		}

		private void ConvertButtonClick(object sender, EventArgs e) {
			try {
				var input_path = _source_file.Text;
				var output_path = _dest_path.Text;

				ValidateInput(input_path, output_path);

				var parser = new Parser(input_path);
				parser.Save(output_path);
			}
			catch (InputValidationException ex) {
				MessageBox.Show(ex.Message);
			}
			catch (ArgumentException ex) {
				MessageBox.Show(ex.Message);
			}
		}
	}
}
